package com.nlx.notes.module.service.impl.flow;

import cn.hutool.core.collection.CollUtil;
import com.nlx.notes.module.bean.dto.FlowSaveDTO;
import com.nlx.notes.module.bean.dto.file.excel.BillRecordDTO;
import com.nlx.notes.module.bean.dto.file.excel.ZfbBillRecordDTO;
import com.nlx.notes.module.bean.vo.AccountVO;
import com.nlx.notes.module.bean.vo.CategoryVO;
import com.nlx.notes.module.bean.vo.category.ThreadCategoryRelVO;
import com.nlx.notes.module.core.enums.TransactionTypeEnum;
import com.nlx.notes.module.core.enums.error.FlowCodeEnum;
import com.nlx.notes.module.core.util.DateUtils;
import com.nlx.notes.module.core.util.JSONUtils;
import com.nlx.notes.module.entity.Categories;
import com.nlx.notes.module.entity.ThirdPartyCategorys;
import com.nlx.notes.module.service.IAccountsService;
import com.nlx.notes.module.service.ICategoriesService;
import com.nlx.notes.module.service.ITransactionsService;
import com.nlx.notes.module.service.category.IThirdPartyCategorysService;
import com.nlx.notes.module.service.flow.FlowExcelService;
import com.nlx.notes.module.service.flow.FlowManageService;
import com.nlx.notes.support.context.UserHolder;
import com.nlx.notes.support.handler.exception.BusinessException;
import com.nlx.notes.support.util.ZFBBillUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

@Slf4j
@Service
@RequiredArgsConstructor(onConstructor_ = @Autowired)
public class FlowExcelServiceImpl implements FlowExcelService {

    final IAccountsService accountsService;

    final ICategoriesService categoriesService;

    final ITransactionsService transactionsService;

    final IThirdPartyCategorysService thirdPartyCategoryService;


    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean saveFlowByExcelData(List<BillRecordDTO> recordList) {
        if(CollUtil.isEmpty(recordList)){
            log.warn("excel中没有读取到对应的数据，线程结束");
        }
        List<AccountVO> accountVOS = accountsService.accountList(UserHolder.getUserContext().getId());
        List<Categories> categories = categoriesService.findListByUser(null,UserHolder.getUserContext().getId());

        Map<String,AccountVO> accountMap = accountVOS.stream().collect(Collectors.toMap(AccountVO::getAccountName, Function.identity()));
        Map<String,Categories> categoryMap = categories.stream().collect(Collectors.toMap(Categories::getName, Function.identity()));

        for (BillRecordDTO billRecordDTO: recordList){
            FlowSaveDTO flowSaveDTO = new FlowSaveDTO();
            flowSaveDTO.setTransactionType(TransactionTypeEnum.EXPEND.getCode());
            flowSaveDTO.setAmount(billRecordDTO.getAmount().toString());
            log.info("分类：{}",billRecordDTO.getSubCategory());
            flowSaveDTO.setCategoryId(categoryMap.get(billRecordDTO.getSubCategory().trim()).getId());
            flowSaveDTO.setAccountId(accountMap.get(billRecordDTO.getAccount1().trim()).getAccountId());
//            flowSaveDTO.setTransactionDate(DateUtils.parseDateTime(billRecordDTO.getDate()));
            flowSaveDTO.setDescription(billRecordDTO.getRemark());
            flowSaveDTO.setUserId(UserHolder.getUserContext().getId());
            log.info("转成的对象：{}", JSONUtils.toString(flowSaveDTO));
            transactionsService.saveFlow(flowSaveDTO);
        }
        log.info("导入完成！");
        return true;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void saveFlowByZfbExcelData(MultipartFile file, String password,Long userId) {
        try {
            File tempFile = File.createTempFile("alipay_"+System.currentTimeMillis(), ".zip");
            file.transferTo(tempFile);
            String child = "unzip_" + System.currentTimeMillis();
            File destDir = new File(tempFile.getParent(), child);
            String billFileName = ZFBBillUtils.unzipWithPassword(tempFile.toPath(),destDir.getAbsolutePath(),password);
            List<ZfbBillRecordDTO> zfbBillRecordDTOS = ZFBBillUtils.readCsv(destDir.getAbsolutePath()+"/"+billFileName);
            if(CollUtil.isEmpty(zfbBillRecordDTOS)){
                log.error("上传的文件没有流水信息");
                throw new BusinessException(FlowCodeEnum.BILL_IS_NOT_DATA);
            }
            List<ThreadCategoryRelVO> thirdPartyCategorysList = thirdPartyCategoryService.findCateGoryByThirdNames("ZFB",userId);
            Map<String,Long> thirdCategoryRelMap = thirdPartyCategorysList.stream().collect(Collectors.
                    toMap(ThreadCategoryRelVO::getThirdCategoryName,ThreadCategoryRelVO::getCategoryId, (oldValue, newValue) -> newValue));
            for (ZfbBillRecordDTO zfbBillRecordDTO: zfbBillRecordDTOS){
                if("不计收支".equals(zfbBillRecordDTO.getTransactionType())){
                    continue;
                }
                String transactionType = "支出".equalsIgnoreCase(zfbBillRecordDTO.getTransactionType()) ? TransactionTypeEnum.EXPEND.getCode(): TransactionTypeEnum.INCOME.getCode();
                String categoryName = zfbBillRecordDTO.getCategory().trim();
                if("其他".equals(categoryName)){
                    if(TransactionTypeEnum.EXPEND.getCode().equalsIgnoreCase(transactionType)){
                        categoryName = "其他支出";
                    }else{
                        categoryName = "其他收入";
                    }
                }
                FlowSaveDTO flowSaveDTO = new FlowSaveDTO();
                flowSaveDTO.setTransactionType(transactionType);
                flowSaveDTO.setAmount(zfbBillRecordDTO.getAmount().toString());
                Long categoryId = thirdCategoryRelMap.get(categoryName);
                if(null == categoryId){
                    categoryId = categoriesService.createCategory(categoryName,transactionType,userId);
                    thirdCategoryRelMap.put(categoryName,categoryId);
                }
                flowSaveDTO.setCategoryId(categoryId);
                flowSaveDTO.setAccountId(1L);
                flowSaveDTO.setTransactionDate(DateUtils.parseDate(zfbBillRecordDTO.getTransactionTime()));
                flowSaveDTO.setDescription(zfbBillRecordDTO.getRemarks());
                flowSaveDTO.setUserId(userId);
                log.info("转成的对象：{}", JSONUtils.toString(flowSaveDTO));
                transactionsService.saveFlow(flowSaveDTO);
            }
            log.info("数据大小：{}"+zfbBillRecordDTOS.size());
        }catch (Exception e){
            throw new BusinessException(FlowCodeEnum.BILL_IMPORT_ERROR);
        }

    }

}
